package me.flyray.bsin.infrastructure.biz.paychannel;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.domain.entity.PayChannelConfig;
import me.flyray.bsin.exception.BusinessException;
import me.flyray.bsin.infrastructure.mapper.PayChannelConfigMapper;
import me.flyray.bsin.payment.channel.wxpay.model.*;
import me.flyray.bsin.payment.enums.PayChannelInterfaceEnum;
import me.flyray.bsin.payment.enums.PayMerchantModeEnum;
import me.flyray.bsin.payment.channel.wxpay.WxServiceUtil;
import me.flyray.bsin.redis.provider.BsinRedisProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicBoolean;

import static me.flyray.bsin.constants.ResponseCode.PAY_CHANNEL_CONFIG_NOT_EXIST;
import static me.flyray.bsin.payment.channel.wxpay.model.WxPayNormalMchParams.REDIS_CERT_PREFIX;

/**
 * @author leonard
 * @description
 * @createDate 2025/07/2025/7/25 /22/51
 */
@Component
@Slf4j
public class PayChannelConfigBiz {

  @Autowired private PayChannelConfigMapper payChannelConfigMapper;

  /**
   * 将接口参数配置对象存入缓存
   *
   * @param payChannelConfig
   */
  public void setPayChannelConfigMapper(PayChannelConfig payChannelConfig) {
    BsinRedisProvider.setCacheObject(
        handle(
            payChannelConfig.getBizRoleAppId(),
            payChannelConfig.getBizRoleTypeNo(),
            payChannelConfig.getPayChannel(),
            payChannelConfig.getMerchantPayMode()),
        payChannelConfig);
    BsinRedisProvider.setCacheObject(handle(payChannelConfig.getSerialNo()), payChannelConfig);
  }

  /**
   * 从缓存中获取参支付数配置对象
   *
   * @param bizRoleAppId 应用ID
   * @param bizRoleTypeNo 平台(渠道)商户ID：平台应用为空，平台商户为商户ID
   * @param payChannel 支付渠道编码
   * @param merchantPayMode 商户模式：1普通商户模式 2特约商户模式 3服务商子商户模式
   */
  public PayChannelConfig getPayChannelConfig(
      String bizRoleAppId, String bizRoleTypeNo, String payChannel, String merchantPayMode) {
    return BsinRedisProvider.getCacheObject(
        handle(bizRoleAppId, bizRoleTypeNo, payChannel, merchantPayMode));
  }

  /**
   * 从缓存中获取参支付数配置对象
   *
   * @param payChannelConfigNo
   */
  public PayChannelConfig getPayChannelConfig(String payChannelConfigNo) {
    return BsinRedisProvider.getCacheObject(handle(payChannelConfigNo));
  }

  /**
   * 从缓存中移除支付参数配置对象
   *
   * @param payChannelConfig
   */
  public void removePayChannelConfig(PayChannelConfig payChannelConfig) {
    BsinRedisProvider.deleteObject(
        handle(
            payChannelConfig.getBizRoleAppId(),
            payChannelConfig.getBizRoleTypeNo(),
            payChannelConfig.getPayChannel(),
            payChannelConfig.getMerchantPayMode()));
    BsinRedisProvider.deleteObject(handle(payChannelConfig.getSerialNo()));
  }

  /**
   * 数据处理
   *
   * @param bizRoleAppId 应用ID
   * @param bizRoleTypeNo 平台(渠道)商户ID：平台应用为空，平台商户为商户ID
   * @param payChannel 支付通道编码
   * @see PayChannelInterfaceEnum
   * @param merchantPayMode 1:普通商户模式 2:特约商户模式 3:服务商子商户模式
   * @return
   */
  String handle(String bizRoleAppId, String bizRoleTypeNo, String payChannel, String merchantPayMode) {
    StringJoiner stringJoiner = new StringJoiner("");
    stringJoiner.add(REDIS_CERT_PREFIX);
    stringJoiner.add(payChannel + "-");
    stringJoiner.add(bizRoleAppId + "-");
    stringJoiner.add(bizRoleTypeNo + "-");
    stringJoiner.add(merchantPayMode + "");
    return stringJoiner.toString();
  }

  /**
   * 数据处理
   *
   * @param payChannelConfigNo
   * @return
   */
  String handle(String payChannelConfigNo) {
    StringJoiner stringJoiner = new StringJoiner("");
    stringJoiner.add(REDIS_CERT_PREFIX);
    stringJoiner.add(payChannelConfigNo + "");
    return stringJoiner.toString();
  }

  /**
   * 数据库查询接口配置
   *
   * @param bizRoleAppId 应用ID
   * @param bizRoleTypeNo 平台(渠道)商户ID：平台应用为空，平台商户为商户ID
   * @param payChannel 支付通道编码
   * @param merchantPayMode 商户模式：1普通商户模式，2特约商户模式，3服务商子商户模式
   * @param isCache 是否从缓存获取的引用传递参数
   * @return
   */
  public PayChannelConfig queryPayChannelConfig(
      String bizRoleAppId,
      String bizRoleTypeNo,
      String payChannel,
      String merchantPayMode,
      AtomicBoolean isCache) {
    // 先从缓存中查询
    PayChannelConfig payChannelConfig =
        getPayChannelConfig(bizRoleAppId, bizRoleTypeNo, payChannel, merchantPayMode);
    if (ObjectUtil.isEmpty(payChannelConfig)) {
      isCache.set(false);
      LambdaQueryWrapper<PayChannelConfig> wrapper = new LambdaQueryWrapper<>();
      wrapper.eq(PayChannelConfig::getStatus, "1");
      wrapper.eq(PayChannelConfig::getBizRoleAppId, bizRoleAppId);
      wrapper.eq(PayChannelConfig::getBizRoleTypeNo, bizRoleTypeNo);
      wrapper.eq(PayChannelConfig::getMerchantPayMode, merchantPayMode);
      wrapper.eq(PayChannelConfig::getPayChannel, payChannel);
      // 查询商户的所有支持的参数配置
      payChannelConfig = payChannelConfigMapper.selectOne(wrapper);

      if (ObjectUtil.isEmpty(payChannelConfig)) {
        log.warn("payChannelConfig is null");
        throw new BusinessException(PAY_CHANNEL_CONFIG_NOT_EXIST);
      }
    } else {
      isCache.set(true);
    }
    return payChannelConfig;
  }

  /**
   * 数据库查询接口配置
   *
   * @param serialNo: 支付通道配置编号
   * @return
   */
  public PayChannelConfig queryPayChannelConfig(String serialNo, AtomicBoolean isCache) {
    // 先从缓存中查询
    PayChannelConfig payChannelConfig = getPayChannelConfig(serialNo);
    if (ObjectUtil.isEmpty(payChannelConfig)) {
      isCache.set(false);
      LambdaQueryWrapper<PayChannelConfig> wrapper = new LambdaQueryWrapper<>();
      wrapper.eq(PayChannelConfig::getStatus, "1");
      wrapper.eq(PayChannelConfig::getSerialNo, serialNo);
      // 查询商户的所有支持的参数配置
      payChannelConfig = payChannelConfigMapper.selectOne(wrapper);

      if (ObjectUtil.isEmpty(payChannelConfig)) {
        log.warn("payChannelConfig is null");
        throw new BusinessException(PAY_CHANNEL_CONFIG_NOT_EXIST);
      }
    } else {
      isCache.set(true);
    }
    return payChannelConfig;
  }

  /**
   * 查询商户的参数配置
   *
   * @param payChannel 支付通道编码
   * @param payChannelConfig
   * @return
   */
  public IsvSubMchParams queryIsvSubMchParams(
      String payChannel, PayChannelConfig payChannelConfig) {
    IsvSubMchParams isvSubMchParams =
        IsvSubMchParams.factory(payChannel, payChannelConfig.getSpecialMerchantParams());

    return isvSubMchParams;
  }

  /**
   * 查询服务商户参数
   *
   * @param
   * @param payChannel 支付通道编码
   */
  public IsvParams queryIsvParams(String payChannel, PayChannelConfig payChannelConfig) {
    log.info("查询服务商户参数");
    IsvParams isvParams = IsvParams.factory(payChannel, payChannelConfig.getIsvParams());
    return isvParams;
  }

  /**
   * 查询商户配置
   *
   * @param payChannel 支付通道编码
   * @param payChannelConfig
   * @return
   * @author ：bolei
   */
  public NormalMchParams queryNormalMchParams(
      String payChannel, PayChannelConfig payChannelConfig) {
    NormalMchParams normalMchParams =
        NormalMchParams.factory(payChannel, payChannelConfig.getNormalMerchantParams());

    return normalMchParams;
  }

  /**
   * 获取支付宝商户服务
   *
   * @param bizRoleAppId 业务角色应用ID
   * @param merchantPayMode
   * @param bizRoleTypeNo 商户号 支付参数对应的商户号，平台应用为空，平台商户为商户ID
   * @param merchantPayMode 商户模式 1-普通商户模式 2-特约商户模式 3-服务商子商户模式
   * @return
   */
  //  public AlipayClientUtil getAlipayClientWrapper(
  //      String bizRoleAppId, String bizRoleTypeNo, String merchantPayMode) {
  //    if (PayMerchantModeEnum.SPECIAL_MERCHANT_MODE.getCode().equals(merchantPayMode)) {
  //
  //      AlipayIsvParams alipayParams =
  //          (AlipayIsvParams) queryIsvParams(bizRoleAppId,
  // PayChannelInterfaceEnum.ALIPAY.getCode());
  //      return AlipayClientUtil.buildAlipayClientWrapper(alipayParams);
  //    } else {
  //      AlipayNormalMchParams alipayParams =
  //          (AlipayNormalMchParams)
  //              queryNormalMchParams(
  //                  bizRoleAppId, bizRoleTypeNo, PayChannelInterfaceEnum.ALIPAY.getCode(),
  // merchantPayMode);
  //      return AlipayClientUtil.buildAlipayClientWrapper(alipayParams);
  //    }
  //  }

  /**
   * 获取微信商户服务
   *
   * @param payChannelConfig
   * @return
   */
  public WxServiceUtil getWxServiceWrapper(PayChannelConfig payChannelConfig) {

    WxServiceUtil wxServiceUtil = null;
    if (PayMerchantModeEnum.SPECIAL_MERCHANT_MODE
        .getCode()
        .equals(payChannelConfig.getMerchantPayMode())) {
      WxPayIsvParams wxParams =
          (WxPayIsvParams)
              IsvParams.factory(
                  PayChannelInterfaceEnum.WXPAY.getCode(), payChannelConfig.getIsvParams());
      wxServiceUtil = WxServiceUtil.buildWxServiceWrapper(wxParams);
    } else {
      WxPayNormalMchParams wxParams =
          (WxPayNormalMchParams)
              NormalMchParams.factory(
                  PayChannelInterfaceEnum.WXPAY.getCode(),
                  payChannelConfig.getNormalMerchantParams());
      wxServiceUtil = WxServiceUtil.buildWxServiceWrapper(wxParams);
    }

    return wxServiceUtil;
  }

  /**
   * 获取微信商户服务
   *
   * @param payChannelConfigNo 支付渠道配置编号
   * @return
   */
  public WxServiceUtil getWxServiceWrapper(String payChannelConfigNo) {

    AtomicBoolean isCache = new AtomicBoolean(true);
    WxServiceUtil wxServiceUtil = null;
    PayChannelConfig payChannelConfig = queryPayChannelConfig(payChannelConfigNo, isCache);

    if (PayMerchantModeEnum.SPECIAL_MERCHANT_MODE
        .getCode()
        .equals(payChannelConfig.getMerchantPayMode())) {
      WxPayIsvParams wxParams =
          (WxPayIsvParams)
              IsvParams.factory(
                  PayChannelInterfaceEnum.WXPAY.getCode(), payChannelConfig.getIsvParams());
      wxServiceUtil = WxServiceUtil.buildWxServiceWrapper(wxParams);
    } else {
      WxPayNormalMchParams wxParams =
          (WxPayNormalMchParams)
              NormalMchParams.factory(
                  PayChannelInterfaceEnum.WXPAY.getCode(),
                  payChannelConfig.getNormalMerchantParams());
      wxServiceUtil = WxServiceUtil.buildWxServiceWrapper(wxParams);
    }

    if (!isCache.get()) {
      log.info("缓存中未查询到参数配置，从数据库中查询，重新写入缓存。。。");
      setPayChannelConfigMapper(payChannelConfig);
    }
    return wxServiceUtil;
  }

}
